home *** CD-ROM | disk | FTP | other *** search
- // MIOTDREM - Async link routines
- // ------------------------------
- //
- // Copyright (c) 1991, Stuart G. Phillips. All rights reserved.
- //
- // Permission is granted for non-commercial use of this software.
- // You are expressly prohibited from selling this software in any form,
- // distributing it with another product, or removing this notice.
- // THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
- // IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
- // WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
- // PURPOSE.
- //
- // This module contains the routines that handle the async link between
- // MIO and TD.
- //
- //
-
-
- #include "miotdr.h"
- #include "mio.h"
- #include "8530.h"
-
- // #define SERIAL_DEBUG to include status of the communications
- // activity. Useful when porting to a new platform in order to
- // see what's going on !
-
- #ifdef SERIAL_DEBUG
-
- struct comm_region { unsigned short status;
- unsigned short scc_status;
- unsigned short scc_special;
- unsigned short int_cnt;
- unsigned short rx_cnt;
- unsigned short tx_cnt;
- unsigned char command;
- };
-
- static struct comm_region *creg = (struct comm_region *)0x80;
-
- #endif
-
- // Static declarations
-
- static void interrupt scc_int();
-
- void send(unsigned char *buffer,
- unsigned short length)
- {
- // Send a packet of [length] bytes to the other end
-
- // Send the length and look for a NULL byte ack
-
- disable();
-
- scc_write(TDSCC|CMD,R1,0); // Disable receive interrupts
-
- // Wait for TX Buffer emp
- while (scc_read(TDSCC|CMD,R0) & Tx_BUF_EMP != Tx_BUF_EMP) ;
-
- scc_wdata(TDSCC|DATA,(unsigned char) length);
-
- #ifdef SERIAL_DEBUG
- creg->tx_cnt++;
- #endif
-
- while ((scc_read(TDSCC|CMD,R0) & Rx_CH_AV) != Rx_CH_AV) ;
- (void) scc_rdata(TDSCC|DATA); // Discard the NULL
-
- // Now send the data
-
- while (length--){
- while ((scc_read(TDSCC|CMD,R0) & Tx_BUF_EMP) != Tx_BUF_EMP) ;
- scc_wdata(TDSCC|DATA,*buffer++);
-
- #ifdef SERIAL_DEBUG
- creg->tx_cnt++;
- #endif
- }
-
- scc_write(TDSCC|CMD,R1,INT_ALL_Rx); // Re-enable receive interrupts
- enable();
- }
-
-
- void send_ack()
- {
- // Send a NULL packet as an acknowledgment
-
- disable();
-
- while ((scc_read(TDSCC|CMD,R0) & Tx_BUF_EMP) != Tx_BUF_EMP) ;
- scc_wdata(TDSCC|DATA,0);
-
- #ifdef SERIAL_DEBUG
- creg->tx_cnt++;
- #endif
-
- enable();
- }
-
-
- void comm_init()
- {
- unsigned char data;
-
- // Set up SCC - this takes a while !
-
- scc_write(TDSCC|CMD,R9,FHWRES); // Reset the SCC
-
- // Loop a while to let reset complete
-
- for (int i=0; i<256; i++) ;
-
- // Set SCC interrupt handler
-
- setvect(0x06,scc_int);
-
- // Set SCC interupt vector and enables
-
- scc_write(TDSCC|CMD,R2,0x06);
- scc_write(TDSCC|CMD,R9,MIE);
-
- scc_write(TDSCC|CMD,R1,INT_ALL_Rx);
-
- // Set Async mode, 8 bits Tx/Rx, 1 stop bit, No parity
-
- scc_write(TDSCC|CMD,R5,DTR|Tx8|TxENAB|RTS);
- scc_write(TDSCC|CMD,R3,Rx8|RxENABLE);
-
- // Set Baud rate generator constant
- // Using 16x clock
- // 9.6 Kbps - 24 (0.16% error - 9615 bps)
- // 19.2 Kbps - 11 (0.16% error - 19230 bps)
- //
- // Using 1x clock
- // 38.4 Kbps - 102 (0.16% error - 38461 bps)
- // 115.0 Kbps - 32 (2.30% error - 117647 bps)
-
- scc_write(TDSCC|CMD,R4,X16CLK|SB1);
- scc_write(TDSCC|CMD,R12,11);
- scc_write(TDSCC|CMD,R13,0);
-
- // Set Baud rate generator source and enable
-
- scc_write(TDSCC|CMD,R11,RCBR|TCBR);
- scc_write(TDSCC|CMD,R14,SSBR|BRSRC|BRENABL);
-
- // Enable 'slave' interupts
-
- data = inportb(IMKW);
- outportb(IMKW,data&~(1 << IRQ7));
-
- enable();
- }
-
-
- static void interrupt scc_int()
- {
- // Interrupts only on receive character or special status change
- unsigned char status;
- register unsigned char length;
- register unsigned char *rxb = (unsigned char *)rx_buffer;
-
- status = scc_read(TDSCC|CMD,R0);
- (void) scc_read(TDSCC|CMD,R1);
-
- #ifdef SERIAL_DEBUG
- creg->int_cnt++;
- #endif
-
- if (status & Rx_CH_AV){
- length = scc_rdata(TDSCC|DATA);
-
- #ifdef SERIAL_DEBUG
- creg->status = length;
- creg->rx_cnt++;
- #endif
-
- // A block of [length] bytes follows
- // A zero count is treated specially - used in the initial handshake
-
- if (length == 0)
- *rxb = TD_SYNC;
- else {
- // Send a NULL acknowledgement
- while ((scc_read(TDSCC|CMD,R0) & Tx_BUF_EMP) != Tx_BUF_EMP) ;
- scc_wdata(TDSCC|DATA,0);
-
- #ifdef SERIAL_DEBUG
- creg->tx_cnt++;
- #endif
-
- while (length--){
- while ((scc_read(TDSCC|CMD,R0) & Rx_CH_AV) != Rx_CH_AV) ;
- *rxb++ = scc_rdata(TDSCC|DATA);
-
- #ifdef SERIAL_DEBUG
- creg->rx_cnt++;
- #endif
- }
- }
-
- msgq = (struct td_imsg *)rx_buffer;
- }
-
- scc_write(TDSCC|CMD,R0,ERR_RES); // Clear special status
- scc_write(TDSCC|CMD,R0,RES_H_IUS); // Reset so we can get next intr.
- outportb(IMDW,ISEOI|IRQ7); // Specific end of intr. to PIC
-
- // Check queued packet to determine if TD issued a stop command.
- // If it did, assume that we're running as an interrupt to program
- // under test - call mc_stop() to return control to MIOTDREM
-
- if (msgq->cmd == TD_STOP)
- mc_stop();
- }
-